<!--created by yuyupeng-->
<!--2023/04/13-->
<!-- 操作日志 -->
<template>
  <div class="list-card-container">
    <a-card title="操作日志" class="general-card">
      <!-- 查询表单 -->
      <AdvancedSearch
        ref="searchRef"
        :data-source="searchItemList"
        @change="searchByParams"
      />

      <!--工具栏：导出-->
      <FileExport
        action="/api/system/operate-log/export"
        file-name="操作日志"
        style="margin-bottom: 10px"
      />

      <!-- 表格 -->
      <a-table
        v-model:selectedKeys="selectedKeys"
        row-key="id"
        column-resizable
        :columns="tbCols"
        :data="tbData"
        :row-selection="rowSelection"
        :pagination="pagination"
        :loading="tbLoading"
        :scroll="{ x: '100%', y: 600 }"
        :scrollbar="true"
        @page-change="onPageChange"
        @page-size-change="onPageSizeChange"
      >
        <!-- 插槽-操作日志详情 -->
        <template #detail="{ record }">
          <a-link type="text" @click="showDetailDrawer(record)"> 详情 </a-link>
        </template>
        <!-- 插槽-一键复制 -->
        <template #quickCopyToolTip="{ record, column }">
          <quick-copy-tool-tip
            :show-text="record[column['dataIndex']]"
            show-btn
          />
        </template>
        <!-- 插槽-用户类型 -->
        <template #userType="{ record }">
          <a-tag v-if="record.userType === '1'" color="gray">普通用户</a-tag>
          <a-tag v-else-if="record.userType === '2'" color="gold"
            >超级管理员</a-tag
          >
          <a-tag v-else-if="record.userType === '3'" color="green"
            >系统管理员</a-tag
          >
          <a-tag v-else-if="record.userType === '4'" color="blue"
            >安全保密管理员</a-tag
          >
          <a-tag v-else-if="record.userType === '5'" color="pinkpurple"
            >安全审计管理员</a-tag
          >
        </template>
        <!-- 插槽-操作分类 -->
        <template #type="{ record }">
          <dictionary-tag
            v-if="operationTypeDictDataSource.length > 0"
            :key="record.type"
            dict-type="operationType"
            :dict-value="String(record.type)"
            :dict-data-source="operationTypeDictDataSource"
          />
        </template>
        <!-- 插槽-用户密级 -->
        <template #secretLevel="{ record }">
          <dictionary-tag
            v-if="secretLevelDictDataSource.length > 0"
            :key="record.secretLevel"
            dict-type="userSecretLevel"
            :dict-value="String(record.secretLevel)"
            :dict-data-source="secretLevelDictDataSource"
          />
        </template>
      </a-table>
    </a-card>
    <!-- 操作日志详情 -->
    <AdvancedShower
      ref="showDrawerRef"
      click="link"
      title="操作日志详情"
      clickword=""
      :data-source="showDrawerConfig"
      :data-record="currentRecord"
    />
  </div>
</template>

<!--新script-->
<script lang="ts" setup>
  import {
    Notification,
    TableColumnData,
    TableRowSelection,
  } from '@arco-design/web-vue';
  import { queryOperationLogRecordList } from '@/api/system/operationLog';
  import { ref, onMounted, reactive } from 'vue';
  import AdvancedSearch from '@/common/components/cac-components/advanced-search/index.vue';
  import AdvancedShower from '@/common/components/cac-components/advanced-shower/index.vue';
  import FileExport from '@/common/components/cac-components/file-export/index.vue';
  import QuickCopyToolTip from '@/common/components/cac-components/quickcopy-tooltip/index.vue';
  import DictionaryTag from '@/common/components/cac-components/dictionary-tag/index.vue';
  import { Pagination } from '@/types/global';
  import {
    OperationLogRecord,
    OperationLogParams,
  } from '@/api/system/model/operationLogModel';
  import {
    DictDataParamsSort,
    DictDataRecord,
  } from '@/api/system/model/dictDataModel';
  import { queryDictDataRecordList } from '@/api/system/dictionary';

  /**
   * data
   */
  // 表格
  const tbData = ref<OperationLogRecord[]>([]);
  const tbCols: TableColumnData[] = [
    {
      title: '序号',
      align: 'center',
      dataIndex: 'index',
      fixed: 'left',
      width: 60,
      render: (row: any) => row.rowIndex + 1,
    },
    /* { title: '日志主键', dataIndex: 'id', fixed: 'left', ellipsis: true, align: 'center', tooltip: true }, */
    {
      title: '查看',
      fixed: 'left',
      align: 'center',
      width: 100,
      slotName: 'detail',
    },
    /* { title: '链路追踪编号', dataIndex: 'traceId', width: 150, align: 'center', tooltip: true, slotName: 'quickCopyToolTip' }, */
    {
      title: '用户编号',
      dataIndex: 'userId',
      width: 150,
      ellipsis: true,
      align: 'center',
      tooltip: true,
      slotName: 'quickCopyToolTip',
    },
    {
      title: '用户类型',
      dataIndex: 'userType',
      width: 150,
      ellipsis: true,
      align: 'center',
      tooltip: true,
      slotName: 'userType',
    },
    {
      title: '用户密级',
      dataIndex: 'secretLevel',
      width: 150,
      ellipsis: true,
      align: 'center',
      tooltip: true,
      slotName: 'secretLevel',
    },
    {
      title: '模块标题',
      dataIndex: 'module',
      width: 150,
      ellipsis: true,
      align: 'center',
      tooltip: true,
      slotName: 'quickCopyToolTip',
    },
    {
      title: '操作名',
      dataIndex: 'name',
      width: 150,
      ellipsis: true,
      align: 'center',
      tooltip: true,
      slotName: 'quickCopyToolTip',
    },
    {
      title: '操作分类',
      dataIndex: 'type',
      width: 150,
      ellipsis: true,
      align: 'center',
      tooltip: true,
      slotName: 'type',
    },
    {
      title: '操作内容',
      dataIndex: 'content',
      width: 150,
      ellipsis: true,
      align: 'center',
      tooltip: true,
    },
    {
      title: '请求方法名',
      dataIndex: 'requestMethod',
      width: 150,
      ellipsis: true,
      align: 'center',
      tooltip: true,
    },
    {
      title: '请求地址',
      dataIndex: 'requestUrl',
      width: 150,
      ellipsis: true,
      align: 'center',
      tooltip: true,
    },
    {
      title: '用户 IP',
      dataIndex: 'userIp',
      width: 150,
      ellipsis: true,
      align: 'center',
      tooltip: true,
    },
    {
      title: '浏览器 UA',
      dataIndex: 'userAgent',
      width: 150,
      ellipsis: true,
      align: 'center',
      tooltip: true,
    },
    {
      title: 'Java 方法名',
      dataIndex: 'javaMethod',
      width: 150,
      ellipsis: true,
      align: 'center',
      tooltip: true,
    },
    {
      title: 'Java 方法的参数',
      dataIndex: 'javaMethodArgs',
      width: 150,
      ellipsis: true,
      align: 'center',
      tooltip: true,
    },
    {
      title: '拓展字段',
      dataIndex: 'exts',
      width: 150,
      ellipsis: true,
      align: 'center',
      tooltip: true,
    },
    {
      title: '操作时间',
      dataIndex: 'startTime',
      width: 150,
      ellipsis: true,
      align: 'center',
      tooltip: true,
    },
    {
      title: '执行时长',
      dataIndex: 'duration',
      width: 150,
      ellipsis: true,
      align: 'center',
      tooltip: true,
    },
    {
      title: '结果码',
      dataIndex: 'resultCode',
      width: 150,
      ellipsis: true,
      align: 'center',
      tooltip: true,
    },
    {
      title: '结果提示',
      dataIndex: 'resultMsg',
      width: 150,
      ellipsis: true,
      align: 'center',
      tooltip: true,
    },
    {
      title: '结果数据',
      dataIndex: 'resultData',
      width: 150,
      ellipsis: true,
      align: 'center',
      tooltip: true,
    },
    /* { title: '创建者', dataIndex: 'creator', width: 150, ellipsis: true, align: 'center', tooltip: true, slotName: 'quickCopyToolTip' },
    { title: '创建时间', dataIndex: 'createTime', width: 150, ellipsis: true, align: 'center', tooltip: true, slotName: 'quickCopyToolTip' },
    { title: '更新者', dataIndex: 'updater', width: 150, ellipsis: true, align: 'center', tooltip: true, slotName: 'quickCopyToolTip' },
    { title: '更新时间', dataIndex: 'updateTime', width: 150, ellipsis: true, align: 'center', tooltip: true, slotName: 'quickCopyToolTip' },
    { title: '更新ip', dataIndex: 'updateIp', width: 150, ellipsis: true, align: 'center', tooltip: true, slotName: 'quickCopyToolTip' },
    { title: '租户编号', dataIndex: 'tenantId', width: 150, ellipsis: true, align: 'center', tooltip: true, slotName: 'quickCopyToolTip' }, */
  ];
  const searchRef = ref<any>();
  const showDrawerRef = ref<any>();
  const currentRecord = ref<OperationLogRecord>(); // 记录当前选择的表格行
  const tbLoading = ref<boolean>(false);
  const operationTypeDictDataSource = ref<DictDataRecord[]>([]); // 操作结果数据字典数据源
  const secretLevelDictDataSource = ref<DictDataRecord[]>([]); // 人员密级数据字典数据源
  // 勾选框
  const selectedKeys = ref([]);
  const rowSelection = reactive<TableRowSelection>({
    type: 'checkbox',
    showCheckedAll: true,
    onlyCurrent: false,
  });
  // 分页，默认第1页，每页10条
  const basePagination: Pagination = {
    current: 1,
    pageSize: 10,
    showPageSize: true,
    showTotal: true,
  };
  const pagination = reactive({
    ...basePagination,
  });
  // 搜索项配置
  const searchItemList = [
    /* { type: 'text', labelText: '日志主键', fieldName: 'id'},
    { type: 'text', labelText: '链路追踪编号', fieldName: 'traceId'}, */
    { type: 'text', labelText: '用户编号', fieldName: 'userId' },
    { type: 'datetimeRange', labelText: '创建时间', fieldName: 'createTime' },
    {
      type: 'dictionary',
      labelText: '操作分类',
      fieldName: 'type',
      dictType: 'operationType',
    },
    /* {
      type: 'select',
      labelText: '用户类型',
      fieldName: 'userType',
      codefield: 'value',
      namefield: 'label',
      options: [
        { label: '普通用户', value: '0' },
        { label: '管理员', value: '1' },
      ],
    }, */
    { type: 'text', labelText: '模块标题', fieldName: 'module' },
    { type: 'text', labelText: '操作名', fieldName: 'name' },
    /* { type: 'text', labelText: '操作内容', fieldName: 'content' },
    { type: 'text', labelText: '拓展字段', fieldName: 'exts' },
    { type: 'text', labelText: '请求方法名', fieldName: 'requestMethod' }, */
    { type: 'text', labelText: '请求地址', fieldName: 'requestUrl' },
    /* { type: 'text', labelText: '用户 IP', fieldName: 'userIp' },
    { type: 'text', labelText: '浏览器 UA', fieldName: 'userAgent' },
    { type: 'text', labelText: 'Java 方法名', fieldName: 'javaMethod' },
    { type: 'text', labelText: 'Java 方法的参数', fieldName: 'javaMethodArgs' },
    { type: 'text', labelText: '操作时间', fieldName: 'startTime' },
    { type: 'text', labelText: '执行时长', fieldName: 'duration' },
    { type: 'text', labelText: '结果码', fieldName: 'resultCode' },
    { type: 'text', labelText: '结果提示', fieldName: 'resultMsg' },
    { type: 'text', labelText: '结果数据', fieldName: 'resultData' }, */
    /* { type: 'text', labelText: '创建者', fieldName: 'creator'},
    { type: 'text', labelText: '创建时间', fieldName: 'createTime'},
    { type: 'text', labelText: '更新者', fieldName: 'updater'},
    { type: 'text', labelText: '更新时间', fieldName: 'updateTime'},
    { type: 'text', labelText: '更新ip', fieldName: 'updateIp'},
    { type: 'text', labelText: '租户编号', fieldName: 'tenantId'}, */
  ];
  // 操作日志详情抽屉配置项
  const showDrawerConfig = [
    /* { type: 'text', labelText: '日志主键', fieldName: 'id'},
    { type: 'text', labelText: '链路追踪编号', fieldName: 'traceId'}, */
    { type: 'text', labelText: '用户编号', fieldName: 'userId' },
    {
      type: 'select',
      labelText: '用户类型',
      fieldName: 'userType',
      codefield: 'value',
      namefield: 'label',
      options: [
        { label: '普通用户', value: '1' },
        { label: '超级管理员', value: '2' },
        { label: '系统管理员', value: '3' },
        { label: '安全保密管理员', value: '4' },
        { label: '安全审计管理员', value: '5' },
      ],
    },
    { type: 'text', labelText: '模块标题', fieldName: 'module' },
    { type: 'text', labelText: '操作名', fieldName: 'name' },
    {
      type: 'dictionary',
      labelText: '操作分类',
      fieldName: 'type',
      dictType: 'operationType',
    },
    { type: 'text', labelText: '操作内容', fieldName: 'content' },
    { type: 'text', labelText: '拓展字段', fieldName: 'exts' },
    {
      type: 'dictionary',
      labelText: '用户密级',
      fieldName: 'secretLevel',
      dictType: 'userSecretLevel',
    },
    { type: 'text', labelText: '请求方法名', fieldName: 'requestMethod' },
    { type: 'text', labelText: '请求地址', fieldName: 'requestUrl' },
    { type: 'text', labelText: '用户 IP', fieldName: 'userIp' },
    { type: 'text', labelText: '浏览器 UA', fieldName: 'userAgent' },
    { type: 'text', labelText: 'Java 方法名', fieldName: 'javaMethod' },
    { type: 'text', labelText: 'Java 方法的参数', fieldName: 'javaMethodArgs' },
    { type: 'text', labelText: '操作时间', fieldName: 'startTime' },
    { type: 'text', labelText: '执行时长', fieldName: 'duration' },
    { type: 'text', labelText: '结果码', fieldName: 'resultCode' },
    { type: 'text', labelText: '结果提示', fieldName: 'resultMsg' },
    { type: 'text', labelText: '结果数据', fieldName: 'resultData' },
    /* { type: 'text', labelText: '创建者', fieldName: 'creator'},
    { type: 'text', labelText: '创建时间', fieldName: 'createTime'},
    { type: 'text', labelText: '更新者', fieldName: 'updater'},
    { type: 'text', labelText: '更新时间', fieldName: 'updateTime'},
    { type: 'text', labelText: '更新ip', fieldName: 'updateIp'},
    { type: 'text', labelText: '租户编号', fieldName: 'tenantId'}, */
  ];
  /**
   * func
   */
  /**
   * @description 根据dictType获取该型字典的所有数据
   * @param dictType 字典类型编码
   */
  const getDictDataDataSource = async (dictType: string) => {
    const params: DictDataParamsSort = {
      dictType,
      orderField: 'sort', // 对sort字段进行排序
      order: 'asc', // 排序方式，分为asc升序 desc降序
    };
    try {
      const { data } = await queryDictDataRecordList(params);
      return data;
    } catch (error) {
      Notification.error({
        content: `出现异常！${error}`,
        closable: true,
      });
      return [];
    }
  };
  /**
   * @method
   * @description 获取表格数据
   */
  const getTbDataByPage = async (reqdata: any = {}) => {
    const params: OperationLogParams = {
      pageNo: pagination.current,
      pageSize: pagination.pageSize,
      ...reqdata,
    };
    tbLoading.value = true;
    selectedKeys.value = [];
    try {
      const { data } = await queryOperationLogRecordList(params);
      tbData.value = data.list;
      tbData.value.forEach((item: OperationLogRecord) => {
        item.userType = String(item.userType); // userType是int类型，如果值为0，不转成String的话AdvancedShower渲染不出来
      });
      pagination.total = Number(data.total); // 用Number函数转一下，否则f12控制台会有警告，很不好看
    } catch (error) {
      // eslint-disable-next-line @typescript-eslint/no-unused-vars
      Notification.error({
        content: `出现异常！${error}`,
        closable: true,
      });
    } finally {
      tbLoading.value = false;
    }
  };
  /**
   * @method
   * @description 按条件搜索
   */
  const searchByParams = (reqdata: any = {}) => {
    getTbDataByPage(reqdata);
  };
  /**
   * @method
   * @description 页码发生变化触发
   */
  const onPageChange = (current: number) => {
    pagination.current = current;
    searchRef.value.handleSubmit(); // 与搜索结果保持一致
  };
  /**
   * @method
   * @description 数据条数发生变化触发
   */
  const onPageSizeChange = (pageSize: number) => {
    pagination.pageSize = pageSize;
    searchRef.value.handleSubmit(); // 与搜索结果保持一致
  };
  /**
   * @description 打开详情抽屉
   * @param record 当前选择的表格行数据
   */
  const showDetailDrawer = (record: OperationLogRecord) => {
    currentRecord.value = record;
    currentRecord.value.type = String(currentRecord.value.type); // 这里有个坑，数据字典只认识String类型的值，如果接口拿到的值是int类型，那么必须要转成String，否则显示不出来
    showDrawerRef.value.showDrawer(); // 打开详情抽屉
  };
  /**
   * onMounted
   */
  onMounted(() => {
    getTbDataByPage();
    getDictDataDataSource('operationType').then((result) => {
      // 操作类型数据字典数据源
      operationTypeDictDataSource.value = result;
    });
    getDictDataDataSource('userSecretLevel').then((result) => {
      // 人员密级数据字典数据源
      secretLevelDictDataSource.value = result;
    });
  });
</script>

<style lang="less" scoped>
  .list-card-container {
    padding: 20px;
    // background-color: var(--color-bg-1);
    border-radius: var(--border-radius-default);
  }
</style>
